home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-05
/
pcb121.zip
/
BRIDGE.INC
< prev
next >
Wrap
Text File
|
1992-01-23
|
11KB
|
329 lines
;;******************************************************************************
;; bridge.inc bridge.inc
;;******************************************************************************
;;
;; Copyright (C) 1989 Northwestern University, Vance Morrison
;;
;;
;; Permission to view, compile, and modify for LOCAL (intra-organization)
;; USE ONLY is hereby granted, provided that this copyright and permission
;; notice appear on all copies. Any other use by permission only.
;;
;; Northwestern University makes no representations about the suitability
;; of this software for any purpose. It is provided "as is" without expressed
;; or implied warranty. See the copywrite notice file for complete details.
;;
;;******************************************************************************
;;
;; Bridge.inc provides ethernet bridge cababilities. Bridge will do bridging
;; between the interfaces provided to it. It will also act like a IF object
;; and return packets that are directed to any of its interfaces.
;;
;; The functions provided by this file are
;;
;; BDG_DECLARE name, start_ifs, end_ifs, forward_ip
;; BDG_DEFINE name
;; BDG_IF_R_ACCESS_out_BX_CX_ES name, no_packet
;; BDG_IF_R_CONT_in_BX_CX_ES_const_BX_CX_DX_BP_SI_DI_ES name, ok
;; BDG_IF_R_FREE_const_BX_CX_BP_SI_DI_ES name
;; BDG_IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP name, no_buffer
;; BDG_IF_W_WRITE_in_CX_const_BX_BP_ES name
;; BDG_IF_SET_ADDRESS_in_SI_const_BX_CX_BP_DI_ES name
;; BDG_IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES name
;;
;; Variables set by this module
;;
;; bdg_&name&_declared ;; one if this interface exists
;; if_&name&_address ;; the hardware address
;; if_&name&_mtu ;; the maximum trans unit
;;
;;******************************************************************************
;;******************************************************************************
;; BDG_DECLARE name, start_ifs, end_ifs, forward_ip
;; BDG_DECLARE declares a bridge made up of the ifs [start_ifs..end_ifs].
;; All of these ifs are assumed to be declared to be PROMISCUOUS and
;; if 'forward_ip' is not blank, then IP broadcasts and ARPS will be
;; forwarded, otherwize they will not
;;
BDG_DECLARE MACRO name, start_ifs, end_ifs, forward_ip
.errb <name>
.errb <start_ifs>
.errb <end_ifs>
if name ne 1
.err ;; you are only alowed 1 bridge and it must be
;; named '1'
endif
.DATA
bdg_&name&_declared = 1
bdg_&name&_start_ifs = start_ifs
bdg_&name&_end_ifs = end_ifs
global bdg_&name&_table_ptr:word ;; holds segement for table
bdg_&name&_forw_ip = 0&forward_ip
.CODE
ENDM
;;******************************************************************************
;; BDG_DEFINE name
;; sets asside memory for the bridge and initializes it.
;; routine is a no-op if 'name' was not declared
;;
BDG_DEFINE MACRO name
LOCAL loop1, loop2, loop3, table
.errb <name>
ifdef bdg_&name&_declared
.data
bdg_&name&_table_ptr dw ? ;; holds segment address of tab
.FarData?
table db 65535 dup (?) ;; set aside a whole segment
;; for the bridge table
.CODE
mov AX, SEG table
mov bdg_&name&_table_ptr, AX ;; remember where the table is
mov ES, AX
xor DI, DI
mov CX, 32768
xor AX, AX
rep
stosw ;; null the bridge table
endif
ENDM
;;******************************************************************************
;; IF_R_ACCESS_out_BX_ES name, no_packet
;; IF_R_ACCESS waits for the next packet to come from the the board
;; associated with 'name' and returns a pointer to the begining of
;; an ethernet packet in BX:ES. CX holds the length of the packet
;; R_ACCESS jumps to 'no_packet' if there are no packets waiting to
;; be read in
;;
BDG_IF_R_ACCESS_out_BX_CX_ES MACRO name, no_packet
local got_packet, forward_all, forward, not_me, drop
local broadcast, broadcast_drop, around
.errb <no_packet>
IF_R_ACCESS_out_BX_CX_ES name, no_packet
mov AX, ES:[BX+4] ;; is this my ethernet address?
cmp AX, word ptr if_&name&_address+4
jnz not_me
mov AX, ES:[BX+2]
cmp AX, word ptr if_&name&_address+2
jnz not_me
mov AX, ES:[BX]
cmp AX, word ptr if_&name&_address
jz got_packet
not_me:
if bdg_1_forw_ip eq 0 ;; drop because it is an IP or ARP packet?
mov AX, word ptr ES:[BX+12]
cmp AX, 0008H ;; is it an IP packet
jz drop
cmp AX, 0608H ;; is it an ARP packet
jz drop
endif
mov BP, DS ;; save DS
mov SI, BX
mov AX, ES
mov ES, bdg_1_table_ptr ;; ES:0 points to the table
mov DS, AX ;; DS:SI points to the packet
add SI, 6 ;; skip to source address of the packet
mov DI, [SI+4] ;; compute hash function ((LSB+MSB) * 8 mod 65k)
xor DI, [SI+2]
shl DI, 1
shl DI, 1
shl DI, 1
movsw ;; save the ethernet address
movsw
movsw
mov AL, name ;; and the fact that it is on this interface
stosb
sub SI, 12 ;; restore SI to the begining of the packet
test byte ptr [SI], 1H ;; is it a broadcast
jnz broadcast
mov DI, [SI+4] ;; compute hash function ((LSB+MSB) * 8 mod 65k)
xor DI, [SI+2]
shl DI, 1
shl DI, 1
shl DI, 1
cmpsw
jnz forward_all ;; didn't find in table
cmpsw
jnz forward_all ;; didn't find in table
cmpsw
jnz forward_all ;; didn't find in table
mov DS, BP ;; restore DS
mov AL, ES:[DI]
cmp AL, name
jnz forward
drop:
IF_R_FREE_const_BX_CX_BP_SI_DI_ES name
jmp no_packet
forward:
mov BP, CX
IRP idx, <1,2,3,4,5,6,7,8>
local next
if (idx le bdg_1_end_ifs) and (idx ge bdg_1_start_ifs)
if idx ne name
cmp AL, idx
jnz next
IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP idx, drop
mov SI, BX
IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES name
mov CX, BP
IF_W_WRITE_in_CX_const_BX_BP_ES idx
next:
endif
endif
endm
jmp drop
forward_all:
mov DS, BP ;; restore DS
mov BP, CX
IRP idx, <1,2,3,4,5,6,7,8>
if (idx le bdg_1_end_ifs) and (idx ge bdg_1_start_ifs)
if idx ne name
mov CX, BP
IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP idx, drop
mov SI, BX
IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES name
mov CX, BP
IF_W_WRITE_in_CX_const_BX_BP_ES idx
endif
endif
endm
jmp drop
broadcast:
mov AX, DS ;; restore ES
mov ES, AX
mov DS, BP ;; restore DS
;; if we don't drop it, then we must send it to all the interfaces
push ES
mov BP, CX
IRP idx, <1,2,3,4,5,6,7,8>
if (idx le bdg_1_end_ifs) and (idx ge bdg_1_start_ifs)
if idx ne name
mov CX, BP
IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP idx, drop
mov SI, BX
IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES name
mov CX, BP
IF_W_WRITE_in_CX_const_BX_BP_ES idx
endif
endif
endm
pop ES
broadcast_drop:
;; in either case, we also send the packet up to the higher level protocols
mov CX, BP ;; restore the length
got_packet:
ENDM
;;******************************************************************************
;; IF_R_FREE_const_BX_CX_BP_SI_DI_ES name
;; After the client is through processing the packet returned by
;; IF_R_ACCESS, IF_R_FREE must be called to inform 'name' that the
;; memory that the packet was in can be reused for future packets.
;;
BDG_IF_R_FREE_const_BX_CX_BP_SI_DI_ES MACRO name
local inside
.errb <name>
IF_R_FREE_const_BX_CX_BP_SI_DI_ES name
ENDM
;;******************************************************************************
;; BDG_IF_R_CONT_in_BX_CX_ES name, ok
;; IF_R_CONT determines if the packet returned by R_ACCESS in BX:ES
;; of length CX is continuous. If it is it jumps to 'ok' otherwise
;; it just returns
;;
BDG_IF_R_CONT_in_BX_CX_ES_const_BX_CX_DX_BP_SI_DI_ES MACRO name, ok
.errb <ok>
IF_R_CONT_in_BX_CX_ES_const_BX_CX_DX_BP_SI_DI_ES name, ok
ENDM
;;******************************************************************************
;; IF_W_ACCESS_in_CX_out_DI_ES name, no_buffer
;; IF_W_ACCESS returns a pointer to an output buffer for a packet. The
;; pointer is returned in DI:ES. If the ouptut buffer is busy, this
;; routine will jump to 'no_buffer'. The output buffer min(CX, 1536)
;; bytes long
;;
BDG_IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP MACRO name, no_buffer
.errb <no_buffer>
IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP name,no_buffer
ENDM
;;******************************************************************************
;; IF_W_WRITE_in_CX name
;; IF_W_WRITE actually signals the ethernet board to write a packet to
;; the ethernet. The packet is assumed to be in the buffer returned by
;; IF_W_ACCESS. CX is the length of the packet to send.
;;
BDG_IF_W_WRITE_in_CX_const_BX_BP_ES MACRO name
.errb <name>
IF_W_WRITE_in_CX_const_BX_BP_ES name
ENDM
;;******************************************************************************
;; IF_SET_ADDRESS_in_SI name
;; IF_SET_ADDRESS_in_SI sets the hardware address to be the value
;; pointed to by SI. Note this function may be a no-op if the
;; hardware address cannot be set (ETHERNET for example)
;;
BDG_IF_SET_ADDRESS_in_SI_const_BX_CX_BP_DI_ES MACRO name
.errb <name>
IF_SET_ADDRESS_in_SI_const_BX_CX_BP_DI_ES name
ENDM
;;******************************************************************************
;; IF_COPY_in_CX_SI_DI_ES name
;; IF_COPY_in_CX_SI_DI_ES copys a packet from the input buffer (pointed
;; to by SI and the segement register given in IF_DECLARE) to an output
;; buffer (pointed to by DI and dest_reg) of length CX. It assumes the
;; output buffer is contiguous. (and the caller shouln't care if the
;; input buffer is contiguous)
;;
BDG_IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES MACRO name
local wrap, done
.errb <name>
IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES name
ENDM